import { Player, PlayerPosition, PlayerRank, Prisma } from '@prisma/client'
import { prisma } from '../utils/database'
import { PlayerSearchParams, CreatePlayerRequest, UpdatePlayerRequest } from '../types/api'
import { createNotFoundError, createConflictError, createDatabaseError } from '../utils/errors'

// 选手完整信息类型（包含位置）
export type PlayerWithPositions = Player & {
  positions: PlayerPosition[]
}

// 格式化选手数据
const formatPlayer = (player: Player, positions: PlayerPosition[]) => {
  return {
    id: player.id,
    nickname: player.nickname,
    rank: player.rank,
    highestMmr: player.highestMmr,
    ability: player.ability,
    tags: player.tags ? JSON.parse(player.tags) : [],
    createdAt: player.createdAt.toISOString(),
    updatedAt: player.updatedAt.toISOString(),
    positions: positions
  }
}

// 获取选手位置
const getPlayerPositions = async (playerId: string): Promise<PlayerPosition[]> => {
  const positionMappings = await prisma.playerPositionMapping.findMany({
    where: { playerId },
    select: { position: true }
  })
  return positionMappings.map(p => p.position)
}

// 获取选手列表（分页搜索）
export const getPlayers = async (params: PlayerSearchParams) => {
  try {
    const {
      page = 1,
      pageSize = 10,
      keyword,
      rank,
      position,
      sortBy = 'createdAt',
      sortOrder = 'desc'
    } = params

    // 构建查询条件
    const where: Prisma.PlayerWhereInput = {}

    // 关键词搜索
    if (keyword && keyword.trim()) {
      where.OR = [
        { id: { contains: keyword.trim() } },
        { nickname: { contains: keyword.trim() } }
      ]
    }

    // 段位筛选
    if (rank && Object.values(PlayerRank).includes(rank as PlayerRank)) {
      where.rank = rank as PlayerRank
    }

    // 位置筛选 - 需要先找到有该位置的选手ID
    if (position && Object.values(PlayerPosition).includes(position as PlayerPosition)) {
      const playerIdsWithPosition = await prisma.playerPositionMapping.findMany({
        where: { position: position as PlayerPosition },
        select: { playerId: true }
      })
      where.id = { in: playerIdsWithPosition.map(p => p.playerId) }
    }

    // 排序
    const orderBy: Prisma.PlayerOrderByWithRelationInput = {}
    orderBy[sortBy] = sortOrder

    // 计算偏移量
    const skip = (page - 1) * pageSize

    // 查询数据
    const [players, total] = await Promise.all([
      prisma.player.findMany({
        where,
        orderBy,
        skip,
        take: pageSize
      }),
      prisma.player.count({ where })
    ])

    // 获取每个选手的位置数据
    const playersWithPositions = await Promise.all(
      players.map(async (player) => {
        const positions = await getPlayerPositions(player.id)
        return formatPlayer(player, positions)
      })
    )

    return {
      items: playersWithPositions,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    }
  } catch (error) {
    console.error('获取选手列表失败:', error)
    throw createDatabaseError('获取选手列表失败')
  }
}

// 根据ID获取选手
export const getPlayerById = async (id: string) => {
  try {
    const player = await prisma.player.findUnique({
      where: { id }
    })

    if (!player) {
      throw createNotFoundError('选手')
    }

    const positions = await getPlayerPositions(player.id)
    return formatPlayer(player, positions)
  } catch (error: any) {
    if (error.name === 'AppError') {
      throw error
    }
    console.error('获取选手详情失败:', error)
    throw createDatabaseError('获取选手详情失败')
  }
}

// 创建选手
export const createPlayer = async (data: CreatePlayerRequest) => {
  try {
    // 检查ID是否已存在
    const existingPlayer = await prisma.player.findUnique({
      where: { id: data.id }
    })

    if (existingPlayer) {
      throw createConflictError('选手ID已存在')
    }

    // 创建选手
    const player = await prisma.player.create({
      data: {
        id: data.id,
        nickname: data.nickname,
        rank: data.rank as PlayerRank,
        highestMmr: data.highestMmr,
        ability: data.ability,
        tags: data.tags ? JSON.stringify(data.tags) : null
      }
    })

    // 创建位置映射
    for (const position of data.positions) {
      await prisma.playerPositionMapping.create({
        data: {
          playerId: player.id,
          position: position as PlayerPosition
        }
      })
    }

    const positions = await getPlayerPositions(player.id)
    return formatPlayer(player, positions)
  } catch (error: any) {
    if (error.name === 'AppError') {
      throw error
    }
    console.error('创建选手失败:', error)
    throw createDatabaseError('创建选手失败')
  }
}

// 更新选手
export const updatePlayer = async (id: string, data: UpdatePlayerRequest) => {
  try {
    // 检查选手是否存在
    const existingPlayer = await prisma.player.findUnique({
      where: { id }
    })

    if (!existingPlayer) {
      throw createNotFoundError('选手')
    }

    // 如果要更新ID，检查新ID是否已存在
    if (data.id && data.id !== id) {
      const playerWithNewId = await prisma.player.findUnique({
        where: { id: data.id }
      })
      if (playerWithNewId) {
        throw createConflictError('新的选手ID已存在')
      }
    }

    // 使用事务更新选手信息
    const updatedPlayer = await prisma.$transaction(async (tx) => {
      // 更新基本信息
      const updateData: any = {}
      if (data.id !== undefined) updateData.id = data.id
      if (data.nickname !== undefined) updateData.nickname = data.nickname
      if (data.rank !== undefined) updateData.rank = data.rank as PlayerRank
      if (data.highestMmr !== undefined) updateData.highestMmr = data.highestMmr
      if (data.ability !== undefined) updateData.ability = data.ability
      if (data.tags !== undefined) updateData.tags = data.tags ? JSON.stringify(data.tags) : null

      let player
      if (Object.keys(updateData).length > 0) {
        player = await tx.player.update({
          where: { id },
          data: updateData
        })
      } else {
        player = existingPlayer
      }

      // 更新位置信息
      if (data.positions !== undefined) {
        // 删除现有位置
        await tx.playerPositionMapping.deleteMany({
          where: { playerId: player.id }
        })

        // 创建新位置
        await tx.playerPositionMapping.createMany({
          data: data.positions.map(position => ({
            playerId: player.id,
            position: position as PlayerPosition
          }))
        })
      }

      // 获取完整的选手信息
      return await tx.player.findUnique({
        where: { id: player.id }
      })
    })

    if (!updatedPlayer) {
      throw createDatabaseError('更新选手失败')
    }

    const positions = await getPlayerPositions(updatedPlayer.id)
    return formatPlayer(updatedPlayer, positions)
  } catch (error: any) {
    if (error.name === 'AppError') {
      throw error
    }
    console.error('更新选手失败:', error)
    throw createDatabaseError('更新选手失败')
  }
}

// 删除选手
export const deletePlayer = async (id: string) => {
  try {
    // 检查选手是否存在
    const existingPlayer = await prisma.player.findUnique({
      where: { id }
    })

    if (!existingPlayer) {
      throw createNotFoundError('选手')
    }

    // 删除选手和位置信息（无外键约束，需要手动删除）
    await prisma.$transaction(async (tx) => {
      // 先删除位置映射
      await tx.playerPositionMapping.deleteMany({
        where: { playerId: id }
      })
      // 再删除选手
      await tx.player.delete({
        where: { id }
      })
    })

    return true
  } catch (error: any) {
    if (error.name === 'AppError') {
      throw error
    }
    console.error('删除选手失败:', error)
    throw createDatabaseError('删除选手失败')
  }
}
